#ifndef MCSR_H
#define MCSR_H
#include <vector>
#include <boost/multi_array.hpp>
#include <iostream>
#include <string>
#include <fstream>
#include <ctime>
#include <boost/timer.hpp>
#include "MCSR.h"
//Compressed Storage Row



using namespace boost;
using namespace std;

template <typename T>
class MCSR
{
	private :
	//attributs
	boost::multi_array<int,1> IA;
	boost::multi_array<int,1> JA;
    vector <T> Values;
	int dim;
	
	public:
	//constructeur
	MCSR(int dim);
	//methode 
	void printIA();
	void printJA();
	void printValues();
	void AjoutElements(T k, int i, int j);
	//produit matrice/vecteur
	void SPMV(const vector <T>& u, vector <T> v);
 };
 
 /****************************************************************************
    * Fonction: MCSR<T>::MCSR()
    * Description: constructeur par parametres
    * Paramètres: int dim1, dimension de la matrice
    * Retour: aucun
    ****************************************************************************/
    template <typename T>
    MCSR<T>::MCSR(int dim1)
   {
	   //par defaut la matrice est une matrice unite
	   dim=dim1;
	   IA.resize(boost::extents[dim+1]);
	   JA.resize(boost::extents[dim]);
	   for(int i=0;i<dim;i++)
	   {
		   IA[i]=1;
		   JA[i]=i; 
		   Values.push_back(1);
	   }   
	   IA[dim]=1;
   }
 
    /****************************************************************************
    * Fonction: MCSR<T>::printIA()
    * Description: affiche les indices des valeur non nuls de la matrice
    * Paramètres: aucun
    * Retour: aucun
    ****************************************************************************/
    template <typename T>
    void MCSR<T>::printIA()
    {
		for(int i=0; i<IA.shape()[0]; i++)
		{
			cout<<IA[i]<<endl;
		}
    }
    /****************************************************************************
    * Fonction: MCSR<T>::printJA()
    * Description: affiche les indices des valeur non nuls de la matrice
    * Paramètres: aucun
    * Retour: aucun
    ****************************************************************************/
    
    template <typename T>
    void MCSR<T>::printJA()
    {
		for(int i=0; i<JA.shape()[0]; i++)
		{
			cout<<JA[i]<<endl;
		}
    }
    /****************************************************************************
    * Fonction: MCSR<T>::printValues()
    * Description: affiche les valeurs non nuls de la matrice
    * Paramètres: aucun
    * Retour: aucun
    ****************************************************************************/
    template <typename T>
    void MCSR<T>::printValues()
    {
		for(int i=0; i<JA.shape()[0]; i++)
		{
			cout<<Values[i]<<endl;
		}
    }
    /****************************************************************************
    * Fonction: MCSR<T>::AjoutElements()
    * Description: Constructeur par paramètres
    * Paramètres: - T k : valeur a ajouter dans le tableau Values
    *             - int nb_lignes: numero de la ligne correspondante
    *             - int nb-colonnes: numero de la colonne correspondante
    *
    * Retour: aucun
    ****************************************************************************/
    template <typename T>
    void MCSR<T>::AjoutElements(T k, int i, int j)
    {
		dim=dim+1;
		IA.resize(boost::extents[dim+1]);
		JA.resize(boost::extents[dim]);
		IA[i+1]=IA[i+1]+1;
		JA[i]=j; //resultat pas bon
		Values.push_back(k);
	}
/****************************************************************************
    * Fonction : SPMV_CSR
    * Description :- calcul le produit matrice_creuse/vecteur et enregistre le temps d'execution et les parametre de la matrice dans un fichier
    *                pour un stockage creux du type Compressed Storage Row, on a un tableau de taille dim+1 qui stocke le nombre d'elements non nuls par ligne
    *                un tableau de taille le nombre de zero qui stocke les numéros des colonne des elements non nuls
    *                et un tableau de taille le nombre de zero qui stocke la valeurs des coefficients non nuls
    * Paramètres : - int *IA, stocke le nombre d'elements non nuls par ligne
    *              - itn *JA stocke les numéros de colonnes des elements non nuls
    *              - T *Values, le tableau de valeurs non nuls
    *              - T *u, le vecteur multiplie
    *              - T *v, le vecteur resultat
    * 			   - int dim la dimension de la matrice
    *              - char* forme, la forme de la matrice
    * Retour: aucun
****************************************************************************/    template <typename T>
    void MCSR<T>::SPMV(const vector <T>& u, vector <T> v)
    {
		string forme="stockage Compressed Storage Row";
		//parametres chronometre
		int compteur;
		int f_compteur=1;
		double temps_moy=0.0000; //temps moyen
		
		
		//while(compteur<f_compteur)
		//{//debut chrono
		timer t;
		t.elapsed();
		for(int i=0;i<dim;i++)
		{
			for(int k=IA[i];k<IA[i+1];k++)
			{
				v[i]=v[i]+Values[k]*u[JA[k]];
					//cout<<"pour creuse : v["<<Indices[i][0]<<"]="<<v[Indices[i][0]]<<endl;
			}
			//fin chrono
			temps_moy=temps_moy+t.elapsed();
			//compteur++;
		}
		    
		temps_moy = temps_moy/((double)f_compteur);
		    
		// ouverture fichier en ecriture seule
		ofstream fichier("creuse_CPP.csv", ios::out | ios::app);
		if(fichier)
		{
			fichier << dim << ";" << forme << ";" << temps_moy << endl;
			fichier.close();
		}			
    }
#endif
